#include "frame_pool.H"


FramePool::FramePool(unsigned long _base_frame_no,
             unsigned long _nframes,
             unsigned long _info_frame_no) {

	base_frame_no = _base_frame_no;
	nframes = _nframes;
	info_frame_no = _info_frame_no;

	if (_info_frame_no == 0) {
	  /*Kernel Frame Pool*/
	  _info_frame_no = (2 * 1024 * 1024) / FRAME_SIZE;
        }	

	free_frames = (UINT8 * ) (_info_frame_no * FRAME_SIZE);

	for (unsigned long i = 0; i < _nframes; i++) {
		*(free_frames + i) = 0;
	}

        for (unsigned long j=0; j< nframes; j++) {
		unsigned long val = *(free_frames + j);
		if (val!=0) {
		Console::puts("VAL :");			
		Console::putui(val);			
		Console::puts("\n");
		}			
	}
        markFrame(_info_frame_no, USED);
}

unsigned long FramePool::get_frame() { 
        unsigned long i;
	UINT8 val;
	Console::puts("ENTER\n");			
        for (i=0; i< nframes; i++) {
		val = *(free_frames + i);
		if (val > 0xFF) {
		Console::puts("ERROR!!\n");			
		Console::puts("VAL :");			
		Console::putui(val);			
		Console::puts("\n");			
		}
		
		if (val != 0xFF)
			break;
	}

	if (val == 0xFF) {
		// No Empty Frame available
		return 0;
	}

	int j = 0;
	while (true) {
		if ((val & (1 << j++)) == 0) break;
		if (j>=8) { Console::puts("ERROR\n"); 
		Console::puts("VAL :");
		Console::putui(val);				for(;;);}					
	}
	unsigned long frame = i*8 + --j;
	markFrame(frame + base_frame_no, USED);
	Console::puts("EXIT\n");			
	return frame + base_frame_no;		
}

void FramePool::mark_inaccessible(unsigned long _base_frame_no,
                          unsigned long _nframes) {
	for (unsigned long i = 0; i < _nframes; i++) {
		   markFrame(_base_frame_no+i);
	}
}

void FramePool::release_frame(unsigned long _frame_no) {
	markFrame(_frame_no, UNUSED);
}

void FramePool::markFrame(unsigned long _frame_no, int isUsed) {
	_frame_no -= base_frame_no;
	UINT8 mask = 0;

	for (int i=0; i<8; i++) {
		if (i!=_frame_no%8)
			mask += 2^i; 
	}

	if (isUsed == USED)
		*(free_frames + _frame_no/8) |= isUsed << _frame_no%8;
	else
		*(free_frames + _frame_no/8) &= mask;
}
